#!/usr/bin/env python
# coding: utf-8

# In[1]:


#数据处理包
import pandas as pd
import numpy as np


# In[83]:


#数据可视化
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
get_ipython().run_line_magic('matplotlib', 'inline')
# 设置全局字体属性
from matplotlib.font_manager import FontProperties
import matplotlib.font_manager as fm
font_path = 'C:/Windows/Fonts/msyh.ttc'  # 确保路径正确
fm.fontManager.addfont(font_path)
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
import seaborn as sns


# In[3]:


#导入
data = pd.read_csv('./1_tianchi_mobile_recommend_train_user.csv')


# In[4]:


data.head()#初探数据


# In[5]:


data.isnull().sum()#查看缺失值


# In[6]:


data.drop('user_geohash',axis=1,inplace=True)#缺失值为地理位置信息，无影响


# In[7]:


#对time列拆分为date列于hour列，用作不同时间维度的分析
data['time']=pd.to_datetime(data['time'])
data['date']=data['time'].dt.date
data['date']=pd.to_datetime(data['date'])
data['hour']=data['time'].dt.hour
data.head()


# In[8]:


#将item_id和item_category转换成str
data.item_id = data.item_id.astype(str)
data.item_category = data.item_category.astype(str)


# In[9]:


#处理异常值
#behavior_type
plt.boxplot(data['behavior_type'])
plt.show()
#hour
# 设置纵坐标范围，并且精度为1
plt.ylim(0, max(data['hour'].max(), 25) + 1)
plt.yticks(np.arange(0, max(data['hour'].max(), 25) + 2, 1))
plt.boxplot(data['hour'])
plt.show()
#即没有超过[1:'浏览', 2:'收藏', 3:'加购物车', 4:'购买'])的行为
#没有超过24小时的异常数据


# In[10]:


#数据分析
#1.用户行为分析
#2.用户价值分析


# In[11]:


#1.1访问量分析
# 日访问量
pv = data.groupby(by='date')['user_id'].count()
# 日独立访客量
uv = data.groupby(by='date')['user_id'].nunique()
# 单独访问量占比
uv_pv = uv / pv * 100

df = pd.concat((pv, uv, uv_pv), axis=1)
df.columns = ['pv', 'uv', 'uv_pv']

# 将占比格式化为字符串显示百分比
df['uv_pv'] = df['uv_pv'].apply(lambda x: '{:.2f}%'.format(x))

# 绘制日独立访问量
plt.figure(figsize=(10, 5))
plt.plot(df.index, df['uv'], color='red')
plt.title('日独立访问量')
plt.xticks(rotation=30)
plt.xlabel('日期')
plt.ylabel('独立访问量')
plt.show()
# 该图显示了每日独立访客量的变化情况。
# 从图中可以看到，在大多数时间里，独立访问量相对稳定，但在某些日期（如2014年12月12日）有显著的峰值。
#这可能是由于某些特别活动或促销引起的访问量激增。


# In[12]:


# 绘制日访问量
plt.figure(figsize=(10, 5))
plt.plot(df.index, df['pv'], color='blue')
plt.title('日访问量')
plt.xticks(rotation=30)
plt.xlabel('日期')
plt.ylabel('访问量')
plt.show()
# 该图展示了每日访问量的变化情况。
# 日访问量与日独立访问量趋势相似，但波动更大。在2014年12月12日，访问量也达到了最高峰，表明在这一天内有大量用户进行多次访问。


# In[13]:


# 使用 'ggplot' 风格绘制单独访问量占比
plt.style.use('ggplot')
plt.figure(figsize=(10, 5))
plt.bar(df.index, df['uv_pv'].str.rstrip('%').astype(float))
plt.title('单独访问量占比')
plt.xticks(rotation=30)
plt.xlabel('日期')
plt.ylabel('占比 (%)')
plt.show()
# 该图展示了每日独立访问量占总访问量的百分比。
# 从图中可以看出，单独访问量占比相对稳定，大多数时间在1.0%到1.75%之间。这表明每天的独立访客数占总访问量的比例基本一致，没有显著波动。


# 推断
# 活动或促销影响：
# 2014年12月12日的独立访问量和总访问量都达到了峰值，表明在这一天有重要的活动或促销吸引了大量用户访问。这可能是一次成功的市场活动。
# 
# 用户行为分析：
# 日独立访问量（UV）和日访问量（PV）的趋势相似，但日访问量的波动更大，表明用户在某些日期访问频次增加。
# 例如，用户在促销活动期间可能会多次访问网站以查看不同的商品或优惠信息。
# 
# 用户粘性：
# 单独访问量占比（UV/PV）相对稳定，说明独立访客数与总访问量之间的关系稳定。即使在访问量激增的情况下，独立访客占比没有显著下降，这表明用户粘性较好，即活动或促销吸引了新用户的同时，也激活了现有用户的多次访问行为。
# 
# 从数据分析和图表可以得出以下结论：
# 在特定日期（如2014年12月12日）可能进行了某种活动或促销，导致了访问量和独立访客量的显著增加。
# 网站在活动期间不仅吸引了大量新用户，还促使现有用户频繁访问，体现了较好的用户粘性。
# 整体上，独立访客占总访问量的比例保持稳定，表明用户行为在大多数时间内是相对一致的。
# 这些推断可以为未来的市场活动和网站运营策略提供参考依据。

# In[14]:


#1.2访问量分析
#分析用户不同行为
behavior=data.groupby(by='behavior_type').count()
behavior.index=['浏览','收藏','加购物车','购买']
behavior.head()


# In[15]:


#计算总用户数量
Sum=behavior['user_id'].sum()
#计算各行为占比
behavior['account']=behavior['user_id']/Sum*100
#各行为代表颜色
colors = ['green','pink','silver','red']
explode=(0.2,0.2,0.2,0.2)
plt.pie(behavior['account'], labels=behavior.index, colors=colors, explode=explode, autopct='%1.1f%%', startangle=140)
plt.axis('equal')
plt.title('各行为占比')
plt.show()


# 根据生成的饼图，可以得出以下结论：
# 
# 浏览行为：
# 占比最大，达到了 94.2%。
# 这表明大多数用户在网站上的主要行为只是浏览内容。
# 
# 收藏行为：
# 占比为 2.0%。
# 相对较少用户会将内容收藏，可能是因为他们还没有明确的购买意图，或者商品不够吸引人。
# 
# 加购物车行为：
# 占比为 1.8%。
# 这表示有一部分用户已经对商品有购买意向，但最终并未完成购买。
# 
# 购买行为：
# 占比为 2.0%。
# 实际完成购买的用户比例较低，表明转化率有提升空间。
# 
# 用户行为分析：
# 大部分用户只是浏览，没有进一步的互动行为（收藏、加购物车、购买）。
# 仅有少数用户会收藏或加购物车，说明用户可能还在观望。
# 实际购买行为比例较低，可能需要改善用户体验或促销策略以提高转化率。
# 
# 优化建议：
# 提高购买转化率：可以通过限时优惠、折扣活动、简化购买流程等手段来提升实际购买行为。
# 用户体验优化：分析用户浏览路径，优化内容展示，提升用户留存和转化。

# In[16]:


# 筛选出12月12日的数据
data_1212 = data[data['date'] == '2014-12-12']

# 计算12月12日当天的点击（浏览）与购买数据
click_1212 = data_1212[data_1212['behavior_type'] == 1]['user_id'].count()
purchase_1212 = data_1212[data_1212['behavior_type'] == 4]['user_id'].count()

# 计算整体数据的点击（浏览）与购买数据
click_total = data[data['behavior_type'] == 1]['user_id'].count()
purchase_total = data[data['behavior_type'] == 4]['user_id'].count()

# 绘制对比图表
labels = ['点击与购买比']
click_purchase_ratio_1212 = click_1212 / purchase_1212 if purchase_1212 != 0 else 0
click_purchase_ratio_total = click_total / purchase_total if purchase_total != 0 else 0

x = range(len(labels))
width = 0.35

fig, ax = plt.subplots(figsize=(8, 6))

rects1 = ax.bar(x, click_purchase_ratio_1212, width, label='12月12日')
rects2 = ax.bar([p + width for p in x], click_purchase_ratio_total, width, label='整体')

ax.set_ylabel('浏览/购买')
ax.set_title('双十二与全年度浏览购买比的对比')
ax.set_xticks([p + width/2 for p in x])
ax.set_xticklabels(labels)
ax.legend()

# 添加数据标签
def autolabel(rects):
    for rect in rects:
        height = rect.get_height()
        ax.annotate(f'{height:.2f}',
                    xy=(rect.get_x() + rect.get_width() / 2, height),
                    xytext=(0, 3),
                    textcoords="offset points",
                    ha='center', va='bottom')

autolabel(rects1)
autolabel(rects2)

plt.show()


# 从图中可以看出：
# 
# 12月12日的点击与购买比为42.06，相对较低，这表明用户在12月12日当天的购买意愿较高，即点击转化为购买的比例较高。
# 整体的点击与购买比为96.09，相对较高，这表明用户在整个时间段内的购买意愿相对较低，即点击转化为购买的比例较低。
# 这说明在12月12日这一天，由于可能有促销活动或其他刺激消费的因素，用户的购买意愿大大提高，导致点击量转化为购买的比例显著上升。
# 
# 结论
# 12月12日这一天的促销活动或其他消费刺激手段，显著提高了用户的购买意愿和购买行为，表现为更高的点击转化为购买的比例。
# 这种现象表明在特定的促销日进行营销活动，可以有效地提高销售转化率。
# 
# 可以将这一天的策略应用到其他促销日或营销活动中，以达到类似的效果。

# In[21]:


#1.3销量分析
#购买的商品
items = data[data['behavior_type']==4]
#按照商品类别分类
items = items.groupby('item_category').count()
items = items.sort_values(by='user_id',ascending=False)#降序排序
items = items.head(10)
items = items[::-1]
plt.barh(items.index,items['user_id'])
plt.xlabel('数量')
plt.ylabel('商品类别')
plt.title('销量前十的商品类别')
plt.show()


# In[46]:


#创建一个透视表，以汇总和分析数据集中不同商品类别在各种行为类型上的数量。
item=data.pivot_table(index='item_category',columns='behavior_type',aggfunc='size',fill_value=0)
# #由前面浏览量占90+%，可以试着将浏览量等比缩小，以获得可视化程度较高的图标
item[1] = item[1] * 0.05  # 将浏览量缩小为原来的5%
#字体冲突，只能注释，1为浏览，2为收藏，3为加购物车，4为购买
sns.set()
item.plot()
plt.show()


# 从图中可以看出：
# 1.收藏量和加购物车量都很大,但销量不高：
# 可能原因：
# 商品价格不合理：价格过高或过低都会影响购买决策。
# 季节性产品：在非季节时段，需求可能较低。
# 解决措施：
# 调整价格：进行市场调研，找到合适的价格区间。
# 季节性促销：在适当的季节进行促销活动，增加曝光和销售。
# 
# 2.收藏量大，但加购物车量少：
# 可能原因：
# 用户在比较多个相似商品，最终只选择一个加入购物车。
# 解决措施：
# 促销活动：如双十二、618等大促活动，吸引用户尽快下单。
# 提供限时优惠：增加紧迫感，促使用户尽快做出购买决策。
# 
# 3.收藏量小：
# 可能原因：
# 商品吸引力不足：可能是商品描述不够详细或图片不够吸引人。
# 解决措施：
# 优惠券：提供优惠券吸引用户收藏和购买。
# 丰富商品信息：增加详细的商品描述和高质量图片，提升商品吸引力。

# In[50]:


# 创建一个透视表，以汇总和分析数据集中不同商品类别在各种行为类型上的数量，并包括日期参数
item = data.pivot_table(index=['item_category', 'date'], columns='behavior_type', aggfunc='size', fill_value=0).reset_index()
# 将浏览量缩小为原来的5%
if 1 in item.columns:
    item[1] = item[1] * 0.05
# 转换为适合绘图的格式
item_stacked = item.set_index(['item_category', 'date']).stack().reset_index()
item_stacked.columns = ['item_category', 'date', 'behavior_type', 'count']
# 绘制三维图表
fig = plt.figure(figsize=(50, 35))
ax = fig.add_subplot(111, projection='3d')
# 获取 X, Y, Z 轴数据
X = pd.Categorical(item_stacked['date']).codes
Y = pd.Categorical(item_stacked['item_category']).codes
Z = item_stacked['count']
C = item_stacked['behavior_type']
# 手动设置 x 和 y 轴范围
ax.set_xlim([X.min() - 10, X.max() + 10])  # 根据数据范围调整数值
ax.set_ylim([Y.min() - 5, Y.max() + 5])  # 根据数据范围调整数值
x_ticks = np.arange(X.min(), X.max(), step=1)  # 减少步长
y_ticks = np.arange(Y.min(), Y.max(), step=1)  # 减少步长
ax.set_xticks(x_ticks)
ax.set_yticks(y_ticks)
# 绘制散点图
sc = ax.scatter(X, Y, Z, c=C, cmap='viridis', marker='o')
# 添加颜色条
fig.colorbar(sc, ax=ax, shrink=0.5, aspect=5)
plt.show()


# In[52]:


#2.1 LTV模型分析
#用户生命价值周期
#平均单人的价值LTV = sum(每天总访问量)/总用户数
total = len(data.groupby('user_id').count())
daily=data.groupby('date').count()
LTV = daily['user_id']/total
LTV.head()


# In[61]:


plt.plot(LTV.index,LTV.values)
plt.xticks(rotation=30)
plt.xlabel('日期')
plt.ylabel('创造的价值')
plt.show()


# 由上图，双十二的创造价值遥遥领先，可以多举办几次类似的促销活动来增加客户价值

# In[68]:


#2.2 RFM分析

# R
# 过滤出购买行为的数据
paid = data[data['behavior_type'] == 4]
# 找到最后一次购买日期
latest = paid['date'].max()
# 计算每个用户最后一次购买日期与最新购买日期的天数差
R = paid.groupby(by='user_id')['date'].apply(lambda x: (latest - x.max()) / np.timedelta64(1, 'D'))
# 打印最大值和均值
print(R.max(), R.mean())
rfm = pd.DataFrame(data=[R,F],index=['R','F']).T
rfm.head()
plt.plot(rfm.index,rfm['R'],color='blue')
plt.legend('R')
plt.show()


# In[66]:


# F
F = paid.groupby(by='user_id')['date'].count()
print(F.max(),F.mean())
plt.plot(rfm.index,rfm['F'],color='red')
plt.legend('F')
plt.show()


# In[70]:


def Rscore(R):
    if R>12:
        return 5
    elif R>9:
        return 4
    elif R>6:
        return 3
    elif R>3:
        return 2
    else:
        return 1
def Fscore(F):
    if F>24:
        return 5
    elif F>18:
        return 4
    elif F>12:
        return 3
    elif F>6:
        return 2
    else:
        return 1
rfm['Rscore']=rfm['R'].apply(Rscore)
rfm['Fscore']=rfm['F'].apply(Fscore)
#求RF均值作为衡量标准
Ravg=rfm['R'].mean()
Favg=rfm['F'].mean()
#R小于均值返回1
def r(a):
    if a<Ravg:
        return '1'
    else:
        return '0'
#F大于均值返回1
def f(a):
    if a>Favg:
        return '1'
    else:
        return '0'
rfm['Rvalue']=rfm['R'].apply(r)
rfm['Fvalue']=rfm['F'].apply(f)
rfm.head(20)


# In[71]:


#客户分类
rfm['rfm']=rfm['Rvalue'].str.cat(rfm['Fvalue'])
def level(x):
    if x=='10':#时间远，频率低
        return '重要吸引客户'
    elif x=='01':#时间近，频率高
        return '重要保持客户'
    elif x=='00':#时间近，频率低
        return '重要推广客户'
    else:#时间远，频率高
        return '重要挽回客户'
rfm['level']=rfm['rfm'].apply(level)
rfm.head(10)


# In[74]:


proportion=rfm.groupby('level').count()
All = proportion['rfm'].sum()
proportion['proportion']=proportion['rfm']/All*100
#图示
colors=["red","gold","silver","blue"]
explode=(0,0,0,0)
plt.pie(proportion['proportion'],explode=explode,labels=proportion.index,colors=colors,shadow=True,autopct='%1.2f%%')
plt.axis('equal')
plt.title('不同用户占比')
plt.show()


# 根据RFM分析结果，不同类型的客户可以采取不同的营销措施：<br />
# <br />
# 重要吸引客户（时间远，频率低）：<br />
# 措施：提供特别优惠或折扣，发送个性化的促销邮件，增加品牌曝光度，吸引他们重新回到平台。<br />
# 重要保持客户（时间近，频率高）：<br />
# 措施：提供忠诚度奖励计划，定期发送感谢邮件或特别优惠，邀请参加VIP活动，确保他们感受到被重视和认可。<br />
# 重要推广客户（时间近，频率低）：<br />
# 措施：提供推荐奖励计划，鼓励他们介绍新客户，发送个性化的产品推荐，增加他们的购买频次。<br />
# 重要挽回客户（时间远，频率高）：<br />
# 措施：发送重新激活邮件，提供特别的回归优惠，了解他们离开的原因并提供解决方案，展示新产品或服务的改进。<br />
# 通过针对不同客户群体采取相应的措施，可以提高客户满意度和忠诚度，从而增加客户的生命周期价值。<br />

# In[86]:


#2.3 留存分析
# font = FontProperties(fname=r'C:\Windows\Fonts\simhei.ttf', size=12)
# 新增用户分析，在第二天及以后依然有使用产品的用户数，即用户留存率
data['date'] = pd.to_datetime(data['date']).dt.date
people = data.pivot_table(index='user_id', columns='date', aggfunc='size', fill_value=0)
# 选择一个子集进行展示
example = people.head(30)
# 设置绘图风格
sns.set(style='whitegrid')
# 绘制热力图
plt.figure(figsize=(15, 10))
sns.heatmap(example, vmin=0, vmax=10, cmap='Blues', cbar_kws={'label': 'active dates'})
# 设置x轴标签格式
plt.xticks(rotation=45, ha='right')
# 设置图表标题和标签
plt.title('Client Retention Analysis')
plt.xlabel('Date')
plt.ylabel('User_ID')
plt.show()


# 从热力图中，我们可以观察到以下几点：</br>
# 
# 活跃用户数的分布：通过颜色的深浅，可以直观地看到用户在一段时间内的活跃情况。颜色越深，表示用户在该天活跃的次数越多。</br>
# 
# 用户留存情况：通过查看用户ID行，可以发现一些用户在多天内保持活跃，而另一些用户仅在少数几天内活跃。这可以帮助我们分析用户的留存情况和使用习惯。</br>
# 
# 趋势和规律：可以分析出特定日期（如促销活动或节假日）用户的活跃情况是否有显著变化。例如，如果在“双十二”期间用户活跃度显著增加，说明促销活动对用户有较强的吸引力。</br>

# In[ ]:




